package com.example.easycharge.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.easycharge.entity.ChargePile;
import com.example.easycharge.error.*;
import com.example.easycharge.notRepEntity.PileData;
import com.example.easycharge.repository.ChargePileRepository;
import com.example.easycharge.service.ChargeService;
import com.example.easycharge.service.PileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "充电桩接口组")
@Slf4j
@RestController
@RequestMapping("pile")
public class PileController {
    @Autowired
    private ChargeService chargeService;
    @Autowired
    private ChargePileRepository chargePileRepository;
    @Autowired
    private PileService pileService;

    @Operation(description = "这个一个新增充电桩的接口，必须的属性都包含在接口里了，其他的属性会自动配置。")
    @PostMapping("admin")
    public JSONObject addNewChargePile(@RequestBody PileData pileData) {
        JSONObject jsonObject = new JSONObject();
        ChargePile chargePile = new ChargePile(pileData);
        chargePile = chargePileRepository.save(chargePile);
        jsonObject.put("message", "新增充电桩成功");
        jsonObject.put("detail", chargePile);
        return jsonObject;
    }

    @Operation(description = "查询单个充电桩的情况")
    @GetMapping("admin/{pileId}")
    public ChargePile getChargePileById(@PathVariable("pileId") long pileId) {
        return chargePileRepository.findChargePileByChargePileId(pileId);
    }

    @Operation(description = "充电桩在安装完成之后需要激活，激活完之后才可以使用")
    @PutMapping("admin/activate/{pileId}")
    public JSONObject activatePile(@PathVariable("pileId") long pileId) throws PileNotFoundError, QueueExistError {
        JSONObject returnJson;
        if (chargePileRepository.countChargePileByChargePileId(pileId) == 0) {
            throw new PileNotFoundError();
        }
        if (chargeService.getPileToQueue().containsKey(pileId)) {
            throw new QueueExistError();
        }
        ChargePile pile = chargePileRepository.findChargePileByChargePileId(pileId);
        returnJson = pileService.addNewQueue(pile);
        return returnJson;
    }

    @Operation(description = "将充电桩设置为故障")
    @PutMapping("admin/error/{pileId}")
    public JSONObject setErrorPile(@PathVariable("pileId") long pileId) throws PileNotFoundError, QueueNotFoundError, ServiceNotSupport {
        if (chargePileRepository.countChargePileByChargePileId(pileId) == 0) {
            throw new PileNotFoundError();
        }
        if (!chargeService.containsPile(pileId)) {
            throw new QueueNotFoundError();
        }
        return pileService.setErrorPile(pileId);
    }

    @Operation(description = "将充电桩从故障中恢复")
    @PutMapping("admin/recovery/{pileId}")
    public JSONObject setRecoveryPile(@PathVariable("pileId") long pileId) throws PileNotFoundError, ServiceNotSupport, QueueExistError, InvalidOperateError, BillNotFoundError, WithoutAuthorityError, QueueNotFoundError {
        if (chargePileRepository.countChargePileByChargePileId(pileId) == 0) {
            throw new PileNotFoundError();
        }
        ChargePile pile = chargePileRepository.findChargePileByChargePileId(pileId);
        if (!pile.isError()) {
            throw new InvalidOperateError();
        }
        return pileService.setRecoveryPile(pileId);
    }

    @Operation(description = "工作中的充电桩可以被关闭（出于某些原因），关闭后的充电桩队列中的车辆会被自动移除（但是还是推荐管理员手动移除）")
    @PutMapping("admin/shutOff/{pileId}")
    public JSONObject shutOffPile(@PathVariable("pileId") long pileId) throws QueueNotFoundError, PileNotFoundError, ServiceNotSupport {
        JSONObject returnJson;
        if (chargePileRepository.countChargePileByChargePileId(pileId) == 0) {
            throw new PileNotFoundError();
        }
        if (!chargeService.containsPile(pileId)) {
            throw new QueueNotFoundError();
        }
        returnJson = pileService.removeQueue(pileId);
        return returnJson;
    }

    @Operation(description = "分页查询所有的充电桩的情况，可用的排序依据有【chargePower、installDate、workHours、chargeHours】")
    @GetMapping("admin/{orderBy}/{page}/{pageNum}/{asc}")
    public Page<ChargePile> getOrderedPile(@PathVariable("orderBy") String orderBy,
                                           @PathVariable("page") int page,
                                           @PathVariable("pageNum") int pageNum,
                                           @PathVariable("asc") boolean asc) {
        Pageable pageable = PageRequest.of(page - 1, pageNum, asc ? Sort.Direction.ASC : Sort.Direction.DESC, orderBy);
        return chargePileRepository.findAll(pageable);
    }

    @Operation(description = "和分页查询充电桩接口很类似，只是支查询激活的或者未激活的")
    @GetMapping("admin/ac/{active}/{orderBy}/{page}/{pageNum}/{asc}")
    public Page<ChargePile> getActivePile(@PathVariable("active") boolean active,
                                          @PathVariable("orderBy") String orderBy,
                                          @PathVariable("page") int page,
                                          @PathVariable("pageNum") int pageNum,
                                          @PathVariable("asc") boolean asc) {
        Pageable pageable = PageRequest.of(page - 1, pageNum, asc ? Sort.Direction.ASC : Sort.Direction.DESC, orderBy);
        return chargePileRepository.findAllByActive(pageable, active);
    }

    @Operation(description = "只查询故障的或者非故障的")
    @GetMapping("admin/er/{error}/{orderBy}/{page}/{pageNum}/{asc}")
    public Page<ChargePile> getErrorPile(@PathVariable("error") boolean error,
                                         @PathVariable("orderBy") String orderBy,
                                         @PathVariable("page") int page,
                                         @PathVariable("pageNum") int pageNum,
                                         @PathVariable("asc") boolean asc) {
        Pageable pageable = PageRequest.of(page - 1, pageNum, asc ? Sort.Direction.ASC : Sort.Direction.DESC, orderBy);
        return chargePileRepository.findAllByError(pageable, error);
    }

    @Operation(description = "根据是否是直流分页获取所有充电桩")
    @GetMapping("admin/dc/{dc}/{orderBy}/{page}/{pageNum}/{asc}")
    public Page<ChargePile> getDCPile(@PathVariable("dc") boolean dc,
                                      @PathVariable("orderBy") String orderBy,
                                      @PathVariable("page") int page,
                                      @PathVariable("pageNum") int pageNum,
                                      @PathVariable("asc") boolean asc) {
        Pageable pageable = PageRequest.of(page - 1, pageNum, asc ? Sort.Direction.ASC : Sort.Direction.DESC, orderBy);
        return chargePileRepository.findAllByDc(pageable, dc);
    }

    @Operation(description = "")
    @PutMapping("admin/setting/{pileId}/{changeItem}/{newValue}")
    public JSONObject updatePileDetail(@PathVariable("pileId") long pileId,
                                       @PathVariable("changeItem") String changeItem,
                                       @PathVariable("newValue") String newValue) throws AttributeNotFoundError, PileNotFoundError {
        ChargePile pile = chargePileRepository.findChargePileByChargePileId(pileId);
        int pileExist = chargePileRepository.countChargePileByChargePileId(pileId);
        changeItem = changeItem.toLowerCase();
        if (pileExist == 0) {
            throw new PileNotFoundError();
        }
        String oldValue;
        switch (changeItem) {
            case "latitude":
                oldValue = pile.getLatitude() + "";
                pile.setLatitude(Double.parseDouble(newValue));
                break;
            case "longitude":
                oldValue = pile.getLongitude() + "";
                pile.setLongitude(Double.parseDouble(newValue));
                break;
            case "chargepower":
                oldValue = pile.getChargePower() + "";
                pile.setChargePower(Integer.parseInt(newValue));
                break;
            case "dc":
                oldValue = pile.isDc() + "";
                pile.setDc(Boolean.parseBoolean(newValue));
                break;
            case "fast":
                oldValue = pile.isFast() + "";
                pile.setFast(Boolean.parseBoolean(newValue));
                break;
            default:
                throw new AttributeNotFoundError();
        }
        chargePileRepository.save(pile);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", "充电桩信息更改成功");
        jsonObject.put("oldValue", oldValue);
        jsonObject.put("newValue", newValue);
        return jsonObject;
    }

    @Operation(description = "获取所有的充电桩的情况，不常用到，但是必须得有这样一个接口")
    @GetMapping("admin/monitor")
    public List<ChargePile> getAllPileMonitor() {
        return chargePileRepository.findAll();
    }

    @Operation(description = "删除充电桩的接口，很少会用到，实际情况大概就是拆了个充电桩？")
    @DeleteMapping("admin/{pileId}")
    public JSONObject deletePileById(@PathVariable("pileId") long pileId) throws PileNotFoundError, PileStillWordError {
        if (chargePileRepository.countChargePileByChargePileId(pileId) == 0) {
            throw new PileNotFoundError();
        }
        if (chargeService.containsPile(pileId)) {
            throw new PileStillWordError();
        }
        return pileService.deletePile(pileId);
    }
}
